package com.ruoyi.mobile.project.ums.controller;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo;
import cn.binarywang.wx.miniapp.bean.WxMaUserInfo;
import com.ruoyi.db.ums.domain.UmsUser;
import com.ruoyi.mobile.annotation.WxLoginUser;
import com.ruoyi.mobile.dto.UserInfo;
import com.ruoyi.mobile.notify.NotifyService;
import com.ruoyi.mobile.project.sms.service.WxCouponAssignService;
import com.ruoyi.mobile.service.UserTokenManager;
import com.ruoyi.mobile.utils.IpUtil;
import com.ruoyi.mobile.utils.JacksonUtil;
import com.ruoyi.mobile.utils.ResponseUtil;
import com.ruoyi.mobile.project.ums.service.WxUmsUserService;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.HashMap;
import java.util.Map;

/**
 * 鉴权服务
 */
@RestController
@RequestMapping("/wx/auth")
@Validated
public class WxAuthController
{
    private final Log logger = LogFactory.getLog(WxAuthController.class);

    @Autowired
    private WxUmsUserService userService;

    @Autowired
    private WxMaService wxMaService;

    @Autowired
    private NotifyService notifyService;

    @Autowired
    private WxCouponAssignService wxCouponAssignService;

    /**
     * 微信登录
     *
     * @param body 请求内容，{ code: xxx, signature: xxx, rawData: xxx, iv: xxx, encryptedData: xxx}
     * @param request     请求对象
     * @return 登录结果
     */
    @PostMapping("login_by_weixin")
    public Object loginByWeixin(@RequestBody String body, HttpServletRequest request)
    {
        //获得相应的参数信息
        String code = JacksonUtil.parseString(body, "code");
        String iv = JacksonUtil.parseString(body, "iv");
        String encryptedData = JacksonUtil.parseString(body, "encryptedData");

        // 验证参数
        if (code == null || iv == null || encryptedData == null)
        {
            return ResponseUtil.badArgument();
        }

        // 获得微信的session key和openid
        String sessionKey = null;
        String openId = null;
        try
        {
            WxMaJscode2SessionResult result = this.wxMaService.getUserService().getSessionInfo(code);
            sessionKey = result.getSessionKey();
            openId = result.getOpenid();
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
        if (sessionKey == null || openId == null)
        {
            return ResponseUtil.fail();
        }

        // 解析加密数据，获得用户的完整信息
        WxMaUserInfo wxMaUserInfo = this.wxMaService.getUserService().getUserInfo(sessionKey, encryptedData, iv);
        if (wxMaUserInfo == null)
        {
            return ResponseUtil.fail();
        }
        String hometown = wxMaUserInfo.getCountry()+"."+wxMaUserInfo.getProvince()+"."+wxMaUserInfo.getCity();

        // 保存或更新微信用户表信息
        UmsUser user = userService.queryByOid(openId);
        if (user == null)
        {
            long now = LocalDateTime.now().toInstant(ZoneOffset.of("+8")).toEpochMilli()/1000;

            user = new UmsUser();
            user.setUsername("微信用户"+now);
            user.setPassword(openId);
            user.setWeixinOpenid(openId);
            user.setAvatar(wxMaUserInfo.getAvatarUrl());
            user.setNickname(wxMaUserInfo.getNickName());
            user.setGender(Integer.parseInt(wxMaUserInfo.getGender()));
            user.setUserLevel(0);
            user.setStatus(0);
            user.setHometown(hometown);
            user.setAddTime(LocalDateTime.now());
            user.setLastLoginTime(LocalDateTime.now());
            user.setLastLoginIp(IpUtil.getIpAddr(request));
            user.setSessionKey(sessionKey);

            userService.add(user);

            // 新用户发送注册优惠券
            wxCouponAssignService.assignForRegister(user.getId());
        }
        else
        {
            // 减少更新的字段
            UmsUser user1 =new UmsUser();
            user1.setId(user.getId());
            user1.setHometown(hometown);
            user1.setLastLoginTime(LocalDateTime.now());
            user1.setLastLoginIp(IpUtil.getIpAddr(request));
            user1.setSessionKey(sessionKey);
            if (userService.updateById(user1) == 0)
            {
                return ResponseUtil.updatedDataFailed();
            }
        }

        // token
        String token = UserTokenManager.generateToken(user.getId());

        // 构建返回的用户信息对象
        UserInfo userInfo = new UserInfo();
        userInfo.setNickName(wxMaUserInfo.getNickName());
        userInfo.setAvatarUrl(wxMaUserInfo.getAvatarUrl());
        userInfo.setCountry(wxMaUserInfo.getCountry());
        userInfo.setProvince(wxMaUserInfo.getProvince());
        userInfo.setCity(wxMaUserInfo.getCity());
        userInfo.setLanguage(wxMaUserInfo.getLanguage());
        userInfo.setGender(Integer.parseInt(wxMaUserInfo.getGender()));

        Map<Object, Object> result = new HashMap<Object, Object>();
        result.put("token", token);
        result.put("userInfo", userInfo);
        return ResponseUtil.ok(result);
    }

    /**
     * 微信手机号码绑定
     *
     * @param userId
     * @param body
     * @return
     */
    @PostMapping("bindPhone")
    public Object bindPhone(@WxLoginUser Long userId, @RequestBody String body)
    {
        if (userId == null)
        {
            return ResponseUtil.unlogin();
        }

        UmsUser user = userService.findById(userId);
        String encryptedData = JacksonUtil.parseString(body, "encryptedData");
        String iv = JacksonUtil.parseString(body, "iv");
        WxMaPhoneNumberInfo phoneNumberInfo = this.wxMaService.getUserService().getPhoneNoInfo(user.getSessionKey(), encryptedData, iv);
        String phone = phoneNumberInfo.getPhoneNumber();
        user.setMobile(phone);

        if (userService.updateById(user) == 0)
        {
            return ResponseUtil.updatedDataFailed();
        }

        return ResponseUtil.ok();
    }

    @PostMapping("logout")
    public Object logout(@WxLoginUser Long userId)
    {
        if (userId == null)
        {
            return ResponseUtil.unlogin();
        }
        return ResponseUtil.ok();
    }

    @GetMapping("info")
    public Object info(@WxLoginUser Long userId)
    {
        if (userId == null)
        {
            return ResponseUtil.unlogin();
        }

        UmsUser user = userService.findById(userId);
        Map<Object, Object> data = new HashMap<Object, Object>();
        data.put("nickName", user.getNickname());
        data.put("avatar", user.getAvatar());
        data.put("gender", user.getGender());
        data.put("mobile", user.getMobile());

        return ResponseUtil.ok(data);
    }

    //    /**
    //     * 账号登录
    //     *
    //     * @param body    请求内容，{ username: xxx, password: xxx }
    //     * @param request 请求对象
    //     * @return 登录结果
    //     */
    //    @PostMapping("login")
    //    public Object login(@RequestBody String body, HttpServletRequest request) {
    //        String username = JacksonUtil.parseString(body, "username");
    //        String password = JacksonUtil.parseString(body, "password");
    //        if (username == null || password == null) {
    //            return ResponseUtil.badArgument();
    //        }
    //
    //        List<UmsUser> userList = userService.queryByUsername(username);
    //        UmsUser user = null;
    //        if (userList.size() > 1) {
    //            return ResponseUtil.serious();
    //        } else if (userList.size() == 0) {
    //            return ResponseUtil.fail(AUTH_INVALID_ACCOUNT, "账号不存在");
    //        } else {
    //            user = userList.get(0);
    //        }
    //
    //        BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
    //        if (!encoder.matches(password, user.getPassword())) {
    //            return ResponseUtil.fail(AUTH_INVALID_ACCOUNT, "账号密码不对");
    //        }
    //
    //        // 更新登录情况
    //        user.setLastLoginTime(LocalDateTime.now());
    //        user.setLastLoginIp(IpUtil.getIpAddr(request));
    //        if (userService.updateById(user) == 0) {
    //            return ResponseUtil.updatedDataFailed();
    //        }
    //
    //        // userInfo
    //        UserInfo userInfo = new UserInfo();
    //        userInfo.setNickName(username);
    //        userInfo.setAvatarUrl(user.getAvatar());
    //
    //        // token
    //        String token = UserTokenManager.generateToken(user.getId());
    //
    //        Map<Object, Object> result = new HashMap<Object, Object>();
    //        result.put("token", token);
    //        result.put("userInfo", userInfo);
    //        return ResponseUtil.ok(result);
    //    }

    //
    //    /**
    //     * 请求注册验证码
    //     *
    //     * TODO
    //     * 这里需要一定机制防止短信验证码被滥用
    //     *
    //     * @param body 手机号码 { mobile }
    //     * @return
    //     */
    //    @PostMapping("regCaptcha")
    //    public Object registerCaptcha(@RequestBody String body) {
    //        String phoneNumber = JacksonUtil.parseString(body, "mobile");
    //        if (StringUtils.isEmpty(phoneNumber)) {
    //            return ResponseUtil.badArgument();
    //        }
    //        if (!RegexUtil.isMobileExact(phoneNumber)) {
    //            return ResponseUtil.badArgumentValue();
    //        }
    //
    //        if (!notifyService.isSmsEnable()) {
    //            return ResponseUtil.fail(AUTH_CAPTCHA_UNSUPPORT, "小程序后台验证码服务不支持");
    //        }
    //        String code = CharUtil.getRandomNum(6);
    //        boolean successful = CaptchaCodeManager.addToCache(phoneNumber, code);
    //        if (!successful) {
    //            return ResponseUtil.fail(AUTH_CAPTCHA_FREQUENCY, "验证码未超时1分钟，不能发送");
    //        }
    //        notifyService.notifySmsTemplate(phoneNumber, NotifyType.CAPTCHA, new String[]{code});
    //
    //        return ResponseUtil.ok();
    //    }
    //
    //    /**
    //     * 账号注册
    //     *
    //     * @param body    请求内容
    //     *                {
    //     *                username: xxx,
    //     *                password: xxx,
    //     *                mobile: xxx
    //     *                code: xxx
    //     *                }
    //     *                其中code是手机验证码，目前还不支持手机短信验证码
    //     * @param request 请求对象
    //     * @return 登录结果
    //     * 成功则
    //     * {
    //     * errno: 0,
    //     * errmsg: '成功',
    //     * data:
    //     * {
    //     * token: xxx,
    //     * tokenExpire: xxx,
    //     * userInfo: xxx
    //     * }
    //     * }
    //     * 失败则 { errno: XXX, errmsg: XXX }
    //     */
    //    @PostMapping("register")
    //    public Object register(@RequestBody String body, HttpServletRequest request) {
    //        String username = JacksonUtil.parseString(body, "username");
    //        String password = JacksonUtil.parseString(body, "password");
    //        String mobile = JacksonUtil.parseString(body, "mobile");
    //        String code = JacksonUtil.parseString(body, "code");
    //        // 如果是小程序注册，则必须非空
    //        // 其他情况，可以为空
    //        String wxCode = JacksonUtil.parseString(body, "wxCode");
    //
    //        if (StringUtils.isEmpty(username) || StringUtils.isEmpty(password) || StringUtils.isEmpty(mobile)
    //                || StringUtils.isEmpty(code)) {
    //            return ResponseUtil.badArgument();
    //        }
    //
    //        List<UmsUser> userList = userService.queryByUsername(username);
    //        if (userList.size() > 0) {
    //            return ResponseUtil.fail(AUTH_NAME_REGISTERED, "用户名已注册");
    //        }
    //
    //        userList = userService.queryByMobile(mobile);
    //        if (userList.size() > 0) {
    //            return ResponseUtil.fail(AUTH_MOBILE_REGISTERED, "手机号已注册");
    //        }
    //        if (!RegexUtil.isMobileExact(mobile)) {
    //            return ResponseUtil.fail(AUTH_INVALID_MOBILE, "手机号格式不正确");
    //        }
    //        //判断验证码是否正确
    //        String cacheCode = CaptchaCodeManager.getCachedCaptcha(mobile);
    //        if (cacheCode == null || cacheCode.isEmpty() || !cacheCode.equals(code)) {
    //            return ResponseUtil.fail(AUTH_CAPTCHA_UNMATCH, "验证码错误");
    //        }
    //
    //        String openId = "";
    //        // 非空，则是小程序注册
    //        // 继续验证openid
    //        if(!StringUtils.isEmpty(wxCode)) {
    //            try {
    //                WxMaJscode2SessionResult result = this.wxMaService.getUserService().getSessionInfo(wxCode);
    //                openId = result.getOpenid();
    //            } catch (Exception e) {
    //                e.printStackTrace();
    //                return ResponseUtil.fail(AUTH_OPENID_UNACCESS, "openid 获取失败");
    //            }
    //            userList = userService.queryByOpenid(openId);
    //            if (userList.size() > 1) {
    //                return ResponseUtil.serious();
    //            }
    //            if (userList.size() == 1) {
    //                UmsUser checkUser = userList.get(0);
    //                String checkUsername = checkUser.getUsername();
    //                String checkPassword = checkUser.getPassword();
    //                if (!checkUsername.equals(openId) || !checkPassword.equals(openId)) {
    //                    return ResponseUtil.fail(AUTH_OPENID_BINDED, "openid已绑定账号");
    //                }
    //            }
    //        }
    //
    //        UmsUser user = null;
    //        BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
    //        String encodedPassword = encoder.encode(password);
    //        user = new UmsUser();
    //        user.setUsername(username);
    //        user.setPassword(encodedPassword);
    //        user.setMobile(mobile);
    //        user.setWeixinOpenid(openId);
    //        user.setAvatar("https://yanxuan.nosdn.127.net/80841d741d7fa3073e0ae27bf487339f.jpg?imageView&quality=90&thumbnail=64x64");
    //        user.setNickname(username);
    //        user.setGender((byte) 0);
    //        user.setUserLevel((byte) 0);
    //        user.setStatus((byte) 0);
    //        user.setLastLoginTime(LocalDateTime.now());
    //        user.setLastLoginIp(IpUtil.getIpAddr(request));
    //        userService.add(user);
    //
    //        // 给新用户发送注册优惠券
    //        wxSmsCouponAssignService.assignForRegister(user.getId());
    //
    //        // userInfo
    //        UserInfo userInfo = new UserInfo();
    //        userInfo.setNickName(username);
    //        userInfo.setAvatarUrl(user.getAvatar());
    //
    //        // token
    //        String token = UserTokenManager.generateToken(user.getId());
    //
    //        Map<Object, Object> result = new HashMap<Object, Object>();
    //        result.put("token", token);
    //        result.put("userInfo", userInfo);
    //        return ResponseUtil.ok(result);
    //    }
    //
    //    /**
    //     * 请求验证码
    //     *
    //     * TODO
    //     * 这里需要一定机制防止短信验证码被滥用
    //     *
    //     * @param body 手机号码 { mobile: xxx, type: xxx }
    //     * @return
    //     */
    //    @PostMapping("captcha")
    //    public Object captcha(@WxLoginUser Integer userId, @RequestBody String body) {
    //        if(userId == null){
    //            return ResponseUtil.unlogin();
    //        }
    //        String phoneNumber = JacksonUtil.parseString(body, "mobile");
    //        String captchaType = JacksonUtil.parseString(body, "type");
    //        if (StringUtils.isEmpty(phoneNumber)) {
    //            return ResponseUtil.badArgument();
    //        }
    //        if (!RegexUtil.isMobileExact(phoneNumber)) {
    //            return ResponseUtil.badArgumentValue();
    //        }
    //        if (StringUtils.isEmpty(captchaType)) {
    //            return ResponseUtil.badArgument();
    //        }
    //
    //        if (!notifyService.isSmsEnable()) {
    //            return ResponseUtil.fail(AUTH_CAPTCHA_UNSUPPORT, "小程序后台验证码服务不支持");
    //        }
    //        String code = CharUtil.getRandomNum(6);
    //        boolean successful = CaptchaCodeManager.addToCache(phoneNumber, code);
    //        if (!successful) {
    //            return ResponseUtil.fail(AUTH_CAPTCHA_FREQUENCY, "验证码未超时1分钟，不能发送");
    //        }
    //        notifyService.notifySmsTemplate(phoneNumber, NotifyType.CAPTCHA, new String[]{code});
    //
    //        return ResponseUtil.ok();
    //    }
    //
    //    /**
    //     * 账号密码重置
    //     *
    //     * @param body    请求内容
    //     *                {
    //     *                password: xxx,
    //     *                mobile: xxx
    //     *                code: xxx
    //     *                }
    //     *                其中code是手机验证码，目前还不支持手机短信验证码
    //     * @param request 请求对象
    //     * @return 登录结果
    //     * 成功则 { errno: 0, errmsg: '成功' }
    //     * 失败则 { errno: XXX, errmsg: XXX }
    //     */
    //    @PostMapping("reset")
    //    public Object reset(@RequestBody String body, HttpServletRequest request) {
    //        String password = JacksonUtil.parseString(body, "password");
    //        String mobile = JacksonUtil.parseString(body, "mobile");
    //        String code = JacksonUtil.parseString(body, "code");
    //
    //        if (mobile == null || code == null || password == null) {
    //            return ResponseUtil.badArgument();
    //        }
    //
    //        //判断验证码是否正确
    //        String cacheCode = CaptchaCodeManager.getCachedCaptcha(mobile);
    //        if (cacheCode == null || cacheCode.isEmpty() || !cacheCode.equals(code))
    //            return ResponseUtil.fail(AUTH_CAPTCHA_UNMATCH, "验证码错误");
    //
    //        List<UmsUser> userList = userService.queryByMobile(mobile);
    //        UmsUser user = null;
    //        if (userList.size() > 1) {
    //            return ResponseUtil.serious();
    //        } else if (userList.size() == 0) {
    //            return ResponseUtil.fail(AUTH_MOBILE_UNREGISTERED, "手机号未注册");
    //        } else {
    //            user = userList.get(0);
    //        }
    //
    //        BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
    //        String encodedPassword = encoder.encode(password);
    //        user.setPassword(encodedPassword);
    //
    //        if (userService.updateById(user) == 0) {
    //            return ResponseUtil.updatedDataFailed();
    //        }
    //
    //        return ResponseUtil.ok();
    //    }
    //
    //    /**
    //     * 账号手机号码重置
    //     *
    //     * @param body    请求内容
    //     *                {
    //     *                password: xxx,
    //     *                mobile: xxx
    //     *                code: xxx
    //     *                }
    //     *                其中code是手机验证码，目前还不支持手机短信验证码
    //     * @param request 请求对象
    //     * @return 登录结果
    //     * 成功则 { errno: 0, errmsg: '成功' }
    //     * 失败则 { errno: XXX, errmsg: XXX }
    //     */
    //    @PostMapping("resetPhone")
    //    public Object resetPhone(@WxLoginUser Integer userId, @RequestBody String body, HttpServletRequest request) {
    //        if(userId == null){
    //            return ResponseUtil.unlogin();
    //        }
    //        String password = JacksonUtil.parseString(body, "password");
    //        String mobile = JacksonUtil.parseString(body, "mobile");
    //        String code = JacksonUtil.parseString(body, "code");
    //
    //        if (mobile == null || code == null || password == null) {
    //            return ResponseUtil.badArgument();
    //        }
    //
    //        //判断验证码是否正确
    //        String cacheCode = CaptchaCodeManager.getCachedCaptcha(mobile);
    //        if (cacheCode == null || cacheCode.isEmpty() || !cacheCode.equals(code))
    //            return ResponseUtil.fail(AUTH_CAPTCHA_UNMATCH, "验证码错误");
    //
    //        List<UmsUser> userList = userService.queryByMobile(mobile);
    //        UmsUser user = null;
    //        if (userList.size() > 1) {
    //            return ResponseUtil.fail(AUTH_MOBILE_REGISTERED, "手机号已注册");
    //        }
    //        user = userService.findById(userId);
    //
    //        BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
    //        if (!encoder.matches(password, user.getPassword())) {
    //            return ResponseUtil.fail(AUTH_INVALID_ACCOUNT, "账号密码不对");
    //        }
    //
    //        user.setMobile(mobile);
    //        if (userService.updateById(user) == 0) {
    //            return ResponseUtil.updatedDataFailed();
    //        }
    //
    //        return ResponseUtil.ok();
    //    }
    //
    //    /**
    //     * 账号信息更新
    //     *
    //     * @param body    请求内容
    //     *                {
    //     *                password: xxx,
    //     *                mobile: xxx
    //     *                code: xxx
    //     *                }
    //     *                其中code是手机验证码，目前还不支持手机短信验证码
    //     * @param request 请求对象
    //     * @return 登录结果
    //     * 成功则 { errno: 0, errmsg: '成功' }
    //     * 失败则 { errno: XXX, errmsg: XXX }
    //     */
    //    @PostMapping("profile")
    //    public Object profile(@WxLoginUser Integer userId, @RequestBody String body, HttpServletRequest request) {
    //        if(userId == null){
    //            return ResponseUtil.unlogin();
    //        }
    //        String avatar = JacksonUtil.parseString(body, "avatar");
    //        Byte gender = JacksonUtil.parseByte(body, "gender");
    //        String nickname = JacksonUtil.parseString(body, "nickname");
    //
    //        UmsUser user = userService.findById(userId);
    //        if(!StringUtils.isEmpty(avatar)){
    //            user.setAvatar(avatar);
    //        }
    //        if(gender != null){
    //            user.setGender(gender);
    //        }
    //        if(!StringUtils.isEmpty(nickname)){
    //            user.setNickname(nickname);
    //        }
    //
    //        if (userService.updateById(user) == 0) {
    //            return ResponseUtil.updatedDataFailed();
    //        }
    //
    //        return ResponseUtil.ok();
    //    }
}
